function MenuLoader(view) {
	this.view = view;
}

MenuLoader.prototype.load = function() {
	var aenigmatesData = [{
		id : "padlock"
	}, {
		id : "brick",
		title : "Another brick in the puzzle"
	}, {
		id : "4queens",
		title : "4 Queens",
		href : "../nqueens/4queens/4queens.html"
	}, {
		id : "hanoi",
		title : "Hanoi towers"
	}, {
		id : "1211",
		title : "1211",
		href : "../sequence1211/sequence1211.html"
	}, {
		id : "lock",
		title : "Strange Lock"
	}, {
		id : "5queens",
		title : "5 Queens",
		href : "../nqueens/5queens/5queens.html"
	}, {
		id : "photopuzzle",
		title : "Photo puzzle"
	}, {
		id : "hanoi4",
		title : "Hanoi towers again?"
	}, {
		id : "6queens",
		title : "6 Queens",
		href : "../nqueens/6queens/6queens.html"
	}, {
		id : "ropes",
		title : "Burning ropes"
	}, {
		id : "7queens",
		title : "7 Queens",
		href : "../nqueens/7queens/7queens.html"
	}, {
		id : "woodenblocks",
		title : "Wooden blocks"
	}, {
		id : "8queens",
		title : "8 Queens",
		href : "../nqueens/8queens/8queens.html"
	}];

	var aenigmates = [];
	var lastSolved = 0;
	for (var level = 1; level <= aenigmatesData.length; level++) {
		var aemigmaData = aenigmatesData[level - 1];
		aenigmates.push(AenigmaBean(aemigmaData, level));
		if (aemigmaData.isSolved()) {
			lastSolved = level;
		}
	}

	for (var i = 0; i < lastSolved; i++) {
		new AEnigmatesStorage(aenigmates[i].getId()).unlock();
	}

	this.view.update(aenigmates);
};

function AenigmaBean(aenigma, level) {
	function toFunction(value) {
		var result;

		if (typeof value !== 'function') {
			result = function() {
				return value;
			};
		} else {
			result = value;
		}

		return result;
	}

	aenigma.getId = toFunction(aenigma.id);
	aenigma.storage = new AEnigmatesStorage(aenigma.id);
	aenigma.getLevel = toFunction(level);
	aenigma.getHref = toFunction(aenigma.href || '../' + aenigma.id + '/' + aenigma.id + ".html");
	aenigma.getTitle = toFunction(aenigma.title || aenigma.id.substring(0, 1).toUpperCase() + aenigma.id.substring(1));
	aenigma.isSolved = function() {
		return this.storage.isSolved();
	};
	aenigma.isUnlocked = function() {
		return this.storage.isUnlocked();
	};

	return aenigma;
}

/**
 * 
 * @param jqMenuContainer
 * @param jqSolvedContainer
 */
function MenuView(jqMenuContainer, jqNumSolved) {
	this.jqMenuContainer = jqMenuContainer;
	this.jqNumSolved = jqNumSolved;
	this.row = null;
}

MenuView.prototype.update = function(aenigmates) {
	var lastWasUnlocked = false;
	function mustAddAenigma(i) {
		return (lastWasUnlocked) || (i === 0);
	}

	var colIndex = 0;
	var row = null;
	var numSolved = 0;
	var numLocked = 0;
	var numAdded = 0;
	for (var i = 0; i < aenigmates.length; i++) {
		var aenigma = aenigmates[i];
		if (colIndex === 0) {
			row = $('<div class="row">');
			this.jqMenuContainer.append(row);
		}
		row.append(this.newEntry(aenigma, mustAddAenigma(i)));
		colIndex = (colIndex + 1) % 2;

		lastWasUnlocked = aenigma.isUnlocked();

		if (aenigma.isSolved()) {
			numSolved++;
		}
		if (!aenigma.isUnlocked()) {
			numLocked++;
		}

		numAdded++;
		if (numLocked >= 2) {
			break;
		}
	}

	if (numAdded % 2 !== 0) {
		row.append(this.newEmptyEntry());
	}

	this.updateNumSolved(numSolved);
};

MenuView.prototype.updateNumSolved = function(numSolved) {
	this.jqNumSolved.text(numSolved);
};

MenuView.prototype.newEmptyEntry = function() {
	var result = this.getTemplate();
	result.removeAttr('href');
	result.html('&nbsp;');

	return result;
};

MenuView.prototype.newEntry = function(aenigma, forceAdd) {
	var result = this.getTemplate();
	result.text(this.createLabel(aenigma));

	var solved = aenigma.isSolved();
	if (solved || forceAdd) {
		result.attr('href', aenigma.getHref());
		if (solved) {
			result.append($('<span class="badge">&#10004;</span>'));
		}
	} else {
		result.removeAttr('href');
		result.addClass('unsolved');
	}

	return result;
};

MenuView.prototype.getTemplate = function() {
	return $('#template').clone().removeAttr('id').removeAttr('style');
};

MenuView.prototype.createLabel = function(aenigma) {
	return aenigma.getTitle();
};
